package com.oswift.utils.common;

import java.io.File;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.oswift.utils.exception.ErrorCode;
import com.oswift.utils.exception.PlatException;

/**
 *
 * 解析XML工具类
 *
 * @author Administrator
 * @version C03 Oct 27, 2012
 * @since OSwift GPM V1.0
 */
public final class XMLParseUtil
{
    /**
     * 日志对象
     */
    private static Logger log = LoggerFactory.getLogger(XMLParseUtil.class);

    private XMLParseUtil()
    {
    }

    /**
     * 解析xml字符串生成对应的Document对象
     *
     * @param xmlString
     *            xml字符串
     * @return Document对象
     * @throws GPMException
     *             通用异常
     */
    public static Document parseXml2Docment(String xmlString)
        throws PlatException
    {
        if ((null != xmlString) && (xmlString.trim().length() != 0))
        {
            try
            {
                // 将获取的字符串解析成一个doc
                return DocumentBuilderFactory.newInstance()
                        .newDocumentBuilder().parse(
                                new InputSource(new StringReader(xmlString)));
            }
            catch (Exception e)
            {
                log.error("Fail to parse the xml[" + xmlString
                        + "] to document object.", e);
                throw new PlatException(ErrorCode.COMMON_PARSE_XML_FAIL, e);
            }
        }
        else
        {
            log.warn("The xml to be parsed to document object is blank.");
            return null;
        }
    }

    /**
     * 从文本对象中获取指定标签的值
     *
     * @param document
     *            文本对象
     * @param tagName
     *            指定的标签名称
     * @return 标签值
     */
    public static String getValueByTag(Document document, String tagName)
    {
        if (null == document)
        {
            log.error("The document object is null.");
        }
        else
        {
            NodeList nodes = document.getElementsByTagName(tagName);
            if (null != nodes && nodes.getLength() == 1)
            {
                return nodes.item(0).getTextContent();
            }
        }

        return null;
    }

    /**
     * 从Document对象中根据tag获取对应值
     *
     * @param document
     *            Document对象
     * @param tagName
     *            tag
     * @return 对应的值
     */
    public static String[] getValuesByTag(Document document, String tagName)
    {
        if (null == document)
        {
            log.error("The document object is null.");
        }
        else
        {
            String[] str = new String[0];
            NodeList nodes = document.getElementsByTagName(tagName);
            if (null != nodes)
            {
                int lenth = nodes.getLength();
                str = new String[lenth];
                for (int i = 0; i < lenth; i++)
                {
                    str[i] = nodes.item(i).getTextContent();
                }
            }
            return str;
        }
        return new String[0];
    }

    /**
     * 获取指定标签下指定属性的值
     *
     * @param document
     *            文本对象
     * @param tagName
     *            标签名称
     * @param attributeName
     *            属性名称
     * @return 属性值
     */
    public static String getAtributeValueByName(Document document,
            String tagName, String attributeName)
    {
        if (null == document)
        {
            log.error("The document object is null.");
        }
        else
        {
            NodeList nodes = document.getElementsByTagName(tagName);
            if (null != nodes && nodes.getLength() == 1)
            {
                Node node = nodes.item(0).getAttributes().getNamedItem(
                        attributeName);
                if (null != node)
                {
                    return node.getNodeValue();
                }

            }
        }
        return null;
    }

    /**
     *
     * 获取结点下所以子结点的值
     *
     * @param document
     *            document对象
     * @param noteName
     *            父结点的名称
     * @return 子结点的所有值
     */
    public static List<Map<String, String>> parseChildNode(Document document,
            String noteName)
    {
        if (null == document)
        {
            log.error("The document object is null.");
            return null;
        }

        // 获取所有结点
        NodeList nodeList = document.getElementsByTagName(noteName);

        if (nodeList != null && nodeList.getLength() > 0)
        {
            List<Map<String, String>> result = new ArrayList<Map<String, String>>();
            for (int i = 0; i < nodeList.getLength(); i++)
            {
                Map<String, String> map = new HashMap<String, String>();
                NodeList childList = nodeList.item(i).getChildNodes();
                for (int j = 0; j < childList.getLength(); j++)
                {
                    String key = childList.item(j).getNodeName();
                    String value = childList.item(j).getTextContent();
                    map.put(key, value);
                }
                result.add(map);
            }
            return result;
        }
        return null;
    }

    /**
     *
     * 不区分文件编码格式，直接读取XML文件
     *
     * @param sourceFile
     *            输入文件
     * @return Document对象
     * @throws TAPSException
     *             TAPS通用异常
     */
    public static Document getDocumentFromFile(String sourceFile)
        throws PlatException
    {
        Document xmlDoc = null;
        try
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();

            // 这个Document就是一个XML文件在内存中的镜像
            xmlDoc = db.parse(new File(sourceFile));
        }
        catch (Exception e)
        {
            log.error("Parse xml file['" + sourceFile + "'] is fail.", e);
            throw new PlatException("Parse xml file is fail.", e);
        }
        return xmlDoc;
    }
}
